package operations;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.lang.reflect.Modifier;
import util.Randomness;

import model.CUT;
import model.PublicFieldDeclared;
import model.StatementKind;
import model.TestClusterBuilder;

public class AssignPublicField extends Operation{
	private final Class<?> declaringClass;
	private final Class<?> cType;
	private  String ref;
	private final Field field;
	private final Object value;

	public AssignPublicField(Class<?> declaringClass,String ref,Class<?> cType, Field field,Object value) {
		this.declaringClass=declaringClass;
		this.cType=cType;
		this.ref = ref;
		this.field = field;
		this.value=value;
	}
	

	public Class<?> getcType() {
		return cType;
	}
	public Class<?> getDeclaringClass() {
		return declaringClass;
	}
	public  String  getRefrence(){
		return this.ref;		
	}
	public  void  setRefrence(String ref_){
		 this.ref=ref_;		
	}

	public  Object  getValue(){
		return this.value;		
	}
	public  Field  getField(){
		return this.field;		
	}

	public static AssignPublicField generate(CUT cut,TestClusterBuilder TestCluster){
//		if(cut.getClazz().equals("java.util.Locale"))
//			System.out.println("AssignConstant.generate: "+cut.getClazz() );
		Map<String, String[]> refFactory = TestCluster.getRefFactory();
		PublicFieldDeclared[]  fields=cut.getFields();
		List <PublicFieldDeclared> fieldsList=Arrays.asList(fields);
		if(fieldsList.size()==0) return null;
		
		PublicFieldDeclared field = fieldsList.get(Randomness.nextRandomInt(fieldsList.size()));
		Class<?> cType=field.getOutputType();
	
		if (Modifier.isFinal(field.getField().getModifiers())) return null;
	
		String 	ref = getReference(field.getField().getDeclaringClass().getName(),refFactory);
		Object value=ValuesGenerator.generatePrimitiveValue(field.getOutputType());

		return	 new AssignPublicField(cut.getClazz(),ref,cType,field.getField(),value);
	}
	public static AssignPublicField recommendedgenerate(Class<?> clz,StatementKind publicFiled, TestClusterBuilder TestCluster){
		Map<String, String[]> refFactory = TestCluster.getRefFactory();

		PublicFieldDeclared field=	(PublicFieldDeclared)publicFiled;
		Class<?> cType=field.getOutputType();
		if (Modifier.isFinal(field.getField().getModifiers())) return null;
		String 	ref = getReference(field.getField().getDeclaringClass().getName(),refFactory);
		Object value=ValuesGenerator.generatePrimitiveValue(field.getOutputType());

		return	 new AssignPublicField(clz,ref,cType,field.getField(),value);
	}
	

	@Override
	public Operation clone() {
		final AssignPublicField clone = new AssignPublicField(declaringClass,ref,cType, field,value);

		return clone;
	}
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		 if (!Modifier.isStatic(this.field.getModifiers()))
			 sb.append("  "+ref+ "."+ field.getName() + " = ");
		 else
				sb.append(field.getDeclaringClass().getName()+"." + field.getName()+ " = ");
		 
		
		if(value == null)  
			sb.append("null".toString() );
		else	
			sb.append( ValuesGenerator.toCodeString(field.getType(),this.value));
		
		return sb.toString();

	}


}
